from abc import ABC, abstractmethod
import uuid
import time
import threading
from collections import OrderedDict
from typing import Any, Optional, List, Dict


class Cache(ABC):
    @abstractmethod
    def generate_id(self, *args, **kwargs):
        pass

    @abstractmethod
    def get(self, id, field):
        pass

    @abstractmethod
    def get_all(self, field_list) -> list:
        pass

    @abstractmethod
    def set(self, id, field, value, ttl=None):
        pass

    @abstractmethod
    def delete(self, id):
        pass

    @abstractmethod
    def clear(self):
        pass


class MemoryCache(Cache):
    """
    改进的内存缓存实现
    
    特性：
    - LRU 淘汰策略
    - TTL 过期机制
    - 线程安全
    - 大小限制
    """
    
    def __init__(self, max_size: int = 1000, default_ttl: int = 3600):
        """
        初始化缓存
        
        Args:
            max_size: 最大缓存条目数（默认1000）
            default_ttl: 默认过期时间（秒，默认1小时）
        """
        self.cache: OrderedDict[str, Dict[str, Any]] = OrderedDict()
        self.expiry: Dict[str, float] = {}  # 存储过期时间戳
        self.max_size = max_size
        self.default_ttl = default_ttl
        self.lock = threading.RLock()  # 可重入锁
        
        # 启动后台清理线程
        self._start_cleanup_thread()
    
    def _start_cleanup_thread(self):
        """启动后台线程定期清理过期数据"""
        def cleanup():
            while True:
                time.sleep(300)  # 每5分钟清理一次
                self._cleanup_expired()
        
        thread = threading.Thread(target=cleanup, daemon=True)
        thread.start()
    
    def _cleanup_expired(self):
        """清理过期的缓存条目"""
        with self.lock:
            current_time = time.time()
            expired_keys = [
                key for key, expiry_time in self.expiry.items()
                if expiry_time < current_time
            ]
            for key in expired_keys:
                self._delete_unsafe(key)
    
    def _delete_unsafe(self, id: str):
        """不加锁的删除操作（内部使用）"""
        if id in self.cache:
            del self.cache[id]
        if id in self.expiry:
            del self.expiry[id]
    
    def _evict_lru(self):
        """淘汰最久未使用的条目"""
        if len(self.cache) >= self.max_size:
            # OrderedDict 的第一个元素是最旧的
            oldest_id = next(iter(self.cache))
            self._delete_unsafe(oldest_id)
    
    def generate_id(self, *args, **kwargs) -> str:
        """生成唯一ID"""
        return str(uuid.uuid4())
    
    def set(self, id: str, field: str, value: Any, ttl: Optional[int] = None):
        """
        设置缓存值
        
        Args:
            id: 缓存ID
            field: 字段名
            value: 值
            ttl: 过期时间（秒），None 使用默认值
        """
        with self.lock:
            # 检查是否需要淘汰
            if id not in self.cache:
                self._evict_lru()
            
            # 设置值
            if id not in self.cache:
                self.cache[id] = {}
            
            self.cache[id][field] = value
            
            # 移到末尾（标记为最近使用）
            self.cache.move_to_end(id)
            
            # 设置过期时间
            ttl = ttl if ttl is not None else self.default_ttl
            self.expiry[id] = time.time() + ttl
    
    def get(self, id: str, field: str) -> Optional[Any]:
        """
        获取缓存值
        
        Args:
            id: 缓存ID
            field: 字段名
            
        Returns:
            缓存值，如果不存在或已过期返回 None
        """
        with self.lock:
            # 检查是否存在
            if id not in self.cache:
                return None
            
            # 检查是否过期
            if id in self.expiry and self.expiry[id] < time.time():
                self._delete_unsafe(id)
                return None
            
            # 检查字段是否存在
            if field not in self.cache[id]:
                return None
            
            # 移到末尾（标记为最近使用）
            self.cache.move_to_end(id)
            
            return self.cache[id][field]
    
    def get_all(self, field_list: List[str]) -> List[Dict[str, Any]]:
        """
        获取所有缓存条目的指定字段
        
        Args:
            field_list: 要获取的字段列表
            
        Returns:
            包含所有条目的列表
        """
        with self.lock:
            current_time = time.time()
            result = []
            
            for id in list(self.cache.keys()):
                # 跳过过期的条目
                if id in self.expiry and self.expiry[id] < current_time:
                    self._delete_unsafe(id)
                    continue
                
                item = {"id": id}
                for field in field_list:
                    item[field] = self.cache[id].get(field)
                result.append(item)
            
            return result
    
    def delete(self, id: str):
        """删除缓存条目"""
        with self.lock:
            self._delete_unsafe(id)
    
    def clear(self):
        """清空所有缓存"""
        with self.lock:
            self.cache.clear()
            self.expiry.clear()
    
    def get_stats(self) -> Dict[str, Any]:
        """获取缓存统计信息"""
        with self.lock:
            return {
                "total_entries": len(self.cache),
                "max_size": self.max_size,
                "usage_percent": (len(self.cache) / self.max_size) * 100,
                "expired_entries": sum(
                    1 for expiry_time in self.expiry.values()
                    if expiry_time < time.time()
                )
            }
    
    def extend_ttl(self, id: str, additional_seconds: int):
        """延长缓存条目的过期时间"""
        with self.lock:
            if id in self.expiry:
                self.expiry[id] += additional_seconds